package org.seckill.service.impl;

import org.apache.commons.collections.MapUtils;
import org.seckill.Common.Const;
import org.seckill.Common.SeckillResult;
import org.seckill.dao.SeckillMapper;
import org.seckill.dao.SuccessKilledMapper;
import org.seckill.dao.cache.RedisDao;
import org.seckill.pojo.Seckill;
import org.seckill.pojo.SuccessKilled;
import org.seckill.service.SeckillService;
import org.seckill.vo.Exporter;
import org.seckill.vo.SeckillExecution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by ASUS on 2017/7/31.
 */
@Service("seckillService")
public class SeckillServiceImpl implements SeckillService {


    @Autowired
    private SeckillMapper seckillMapper;

    @Autowired
    private SuccessKilledMapper successKilledMapper;

    @Autowired
    private RedisDao redisDao;

    private static Logger logger = LoggerFactory.getLogger(SeckillServiceImpl.class);

    private static final String stal = "asgilashglasgboiw459207*(^^$^$#%<>?mgkdsgbkasadghoab";

    @Override
    public List<Seckill> getSeckillAll() {
        return seckillMapper.selectALl();
    }

    @Override
    public Seckill getSeckill(Long seckillId) {
        if (seckillId != null) {
            return seckillMapper.selectByPrimaryKey(seckillId);
        }
        return null;
    }

    @Override
    public Exporter exportSeckillUrl(Long seckillId) {
        //缓存优化
        Seckill seckill = redisDao.getSeckill(seckillId);
        if (seckill == null) {
            seckill = seckillMapper.selectByPrimaryKey(seckillId);
            if (seckill != null) {
                redisDao.putSeckill(seckill);
            } else {
                return new Exporter(false);
            }
        }

        Date start = seckill.getStartTime();
        Date end = seckill.getEndTime();
        Date now = new Date();
        if (now.getTime() > end.getTime() || now.getTime() < start.getTime()) {
            return new Exporter(false, seckillId, now.getTime(), start.getTime(), end.getTime());
        }
        String md5 = getMD5(seckillId.toString());
        return new Exporter(true, md5, seckillId);
    }

    @Override
    public SeckillExecution executeSeckillByProcedure(Long seckillId, long userPhone, String md5)  {
        if (md5 == null || !md5.equals(getMD5(seckillId.toString()))) {
            return new SeckillExecution(seckillId,Const.SeckillStatus.DATA_REWRITE.getStatus(),Const.SeckillStatus.DATA_REWRITE.getDesc());
        }
        Map<String,Object> map = new HashMap<>();
        map.put("seckillId",seckillId);
        map.put("phone",userPhone);
        map.put("killTime",new Date());
        map.put("result",null);
        try {
            seckillMapper.seckillByProcedure(map);
            int result = MapUtils.getInteger(map,"result");
            if(result==1){
                SuccessKilled successKilled =  successKilledMapper.selectByPrimaryKey(userPhone);
                return new SeckillExecution(seckillId,Const.SeckillStatus.SUCCESS.getStatus(),Const.SeckillStatus.SUCCESS.getDesc(),successKilled);

            }else {
                return new SeckillExecution(seckillId,result,Const.SeckillStatus.getSeckillStatus(result).getDesc());
            }
        } catch (Exception e) {
            return new SeckillExecution(seckillId,Const.SeckillStatus.INNER_ERROR.getStatus(),Const.SeckillStatus.INNER_ERROR.getDesc());
        }
    }

    private String getMD5(String s) {
        String base = s + "/" + stal;
        String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
        return md5;
    }

//    @Override
//    @Transactional
//    public SeckillExecution executeSeckill(Long seckillId, long userPhone, String md5) throws Exception {
//        try {
//            if (md5 == null || !md5.equals(getMD5(seckillId.toString()))) {
//                logger.error(Const.SeckillStatus.DATA_REWRITE.getDesc());
//                throw new RuntimeException();
//            }
//            Date now = new Date();
//
//            SuccessKilled successKilled = new SuccessKilled(userPhone, seckillId, (byte) 1, now);
//            int resultRow = successKilledMapper.insert(successKilled);
//            if (resultRow == 0) {
//                logger.error(Const.SeckillStatus.REPEAT_KILL.getDesc());
//                throw new RuntimeException();
//            } else {
//                successKilled = successKilledMapper.selectByPrimaryKey(userPhone);
//
//                resultRow = seckillMapper.reduceNumber(seckillId, now);
//                if (resultRow == 0) {
//                    logger.error("减少库存失败");
//                    throw new RuntimeException();
//                } else {
//                    return new SeckillExecution(seckillId, Const.SeckillStatus.SUCCESS.getStatus(), Const.SeckillStatus.SUCCESS.getDesc(), successKilled);
//                }
//            }
//        } catch (Exception e) {
//            logger.error(e.getMessage(), e);
//            throw new RuntimeException(e.getMessage());
//        }
//    }


}
